export class AStar{
    mapInfo:mapInfo=null;
    openList=[];

    constructor(map){
        this.mapInfo=map;
    }
    startSearchPath(currentInfo:nodeInfo,targetInfo:nodeInfo){
        this.clean();
        currentInfo.g = 0;
        currentInfo.h = this.manhattan(currentInfo, targetInfo);
        currentInfo.f = currentInfo.g + currentInfo.h;
        this.openList.push(currentInfo);        
        return this.searchPath1(targetInfo);
    }
    searchPath1(targetInfo:nodeInfo){
        while(this.openList.length>0){
            let minIndex=0;
            let currentInfo:nodeInfo= this.openList.reduce((pre,current,index)=>{
                if(pre.f>current.f){
                    minIndex=index;
                    return current;
                }
                return pre;
            })
            this.openList[minIndex]=this.openList[this.openList.length-1];
            this.openList.pop();
            this.mapInfo.map[currentInfo.row][currentInfo.col].bInClose=true;

            if(currentInfo.row==targetInfo.row&&currentInfo.col==targetInfo.col){
                let path=[]
                path.push(currentInfo);
                while(!currentInfo.parent==false){
                    path.push(currentInfo);  
                    currentInfo=currentInfo.parent;  
                    console.log(currentInfo.row,currentInfo.col)                            
                }
                console.log("找到了");
                return path;
            }      
            let row = currentInfo.row;
            let col = currentInfo.col;

            let neighbors:nodeInfo[] = []   
            if(row+1<this.mapInfo.height)
                neighbors.push(this.mapInfo.map[row+1][col])
            if(row-1>=0)
                neighbors.push(this.mapInfo.map[row-1][col])
            if(col+1<this.mapInfo.width)
                neighbors.push(this.mapInfo.map[row][col+1])
            if(col-1>=0)
                neighbors.push(this.mapInfo.map[row][col-1])
            let next:nodeInfo = {
                row:0,
                col:0,
                f:0
            };    
            let f,g,h=0;
            for(let neighbor of neighbors){
                if (neighbor.bInClose||neighbor.type!=0) {
                    continue;
                }
                g = currentInfo.g+1;
                h = this.manhattan(neighbor,targetInfo);
                f=g+h;

                if(neighbor.bInOpen){
                    if(f<neighbor.f){
                        neighbor.f=f;
                        neighbor.g=g;
                        neighbor.h=h;
                        neighbor.parent=currentInfo;
                    }
                }
                else{
                    neighbor.f=f;
                    neighbor.g=g;
                    neighbor.h=h;
                    neighbor.parent=currentInfo;
                    neighbor.bInOpen=true;
                    this.openList.push(neighbor);
                }
            }
        }
        return [];
    }

    searchPath(targetInfo:nodeInfo){
        if(this.openList.length==0){
            console.log("没路")
            return [];
        }
        let minIndex=0;
        for(let item of this.openList){
            console.log("1=",item);
        }

        let currentInfo:nodeInfo= this.openList.reduce((pre,current,index)=>{
            if(pre.f>current.f){
                minIndex=index;
                return current;
            }
            return pre;
        })

        this.openList[minIndex]=this.openList[this.openList.length-1];
        this.openList.pop();
        this.mapInfo.map[currentInfo.row][currentInfo.col].bInClose=true;

        if(currentInfo.row==targetInfo.row&&currentInfo.col==targetInfo.col){
            let path=[]
            path.push(currentInfo);
            while(!currentInfo.parent==false){
                path.push(currentInfo);  
                currentInfo=currentInfo.parent;                              
            }
            console.log("找到了");
            return path;
        }            

        let row = currentInfo.row;
        let col = currentInfo.col;

        let neighbors:nodeInfo[] = []   
        if(row+1<this.mapInfo.height)
            neighbors.push(this.mapInfo.map[row+1][col])
        if(row-1>=0)
            neighbors.push(this.mapInfo.map[row-1][col])
        if(col+1<this.mapInfo.width)
            neighbors.push(this.mapInfo.map[row][col+1])
        if(col-1>=0)
            neighbors.push(this.mapInfo.map[row][col-1])
        let next:nodeInfo = {
            row:0,
            col:0,
            f:0
        };    
        let f,g,h=0;
        for(let neighbor of neighbors){
            if (neighbor.bInClose||neighbor.type!=0) {
                continue;
            }
            g = currentInfo.g+1;
            h = this.manhattan(neighbor,targetInfo);
            f=g+h;

            if(neighbor.bInOpen){
                if(f<neighbor.f){
                    neighbor.f=f;
                    neighbor.g=g;
                    neighbor.h=h;
                    neighbor.parent=currentInfo;
                }
            }
            else{
                neighbor.f=f;
                neighbor.g=g;
                neighbor.h=h;
                neighbor.parent=currentInfo;
                neighbor.bInOpen=true;
                this.openList.push(neighbor);
            }
        }                
        return this.searchPath(targetInfo);
    }
    clean(){
        this.openList=[]
        for(let i=0;i<this.mapInfo.height;++i){
            for(let j=0;j<this.mapInfo.width;++j){
                this.mapInfo.map[i][j].f=0;
                this.mapInfo.map[i][j].g=0;
                this.mapInfo.map[i][j].h=0;
                this.mapInfo.map[i][j].bInOpen=false;
                this.mapInfo.map[i][j].bInClose=false;
                this.mapInfo.map[i][j].parent=null;
            }
        }
    }
    manhattan(current:nodeInfo,target:nodeInfo){
        return Math.abs(current.row-target.row)+Math.abs(current.col-target.col);
    }
}